package info.hexin.dubbo.stop;

import com.alibaba.dubbo.registry.support.AbstractRegistryFactory;
import info.hexin.dubbo.util.ThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ConfigurableApplicationContext;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * Created by Administrator on 2016/2/2.
 */
public class StopApp {
    static Logger logger = LoggerFactory.getLogger(StopApp.class);

    private static int scan_lock_file_interval = 2 * 1000;

    /**
     * 包可用，防止外面使用
     *
     * @param context
     */
    static void RegisterStopApp(final File lockFile, final ConfigurableApplicationContext context, final Callable callable) {
        new Thread() {
            @Override
            public void run() {
                long lastModified = lockFile.lastModified();
                if (callable != null) {
                    logger.info(">>>> 注册ShutdownHook");
                    Runtime.getRuntime().addShutdownHook(new Thread() {
                        @Override
                        public void run() {
                            try {
                                logger.info(">>>> ShutdownHook被调用");
                                callable.call();
                            } catch (Exception e) {
                                e.printStackTrace(System.err);
                                logger.error("error >> 注册ShutdownHook", e);
                            }
                        }
                    });
                }


                while (true) {
                    try {
                        Thread.sleep(scan_lock_file_interval);
                        long tmpLastModified = lockFile.lastModified();
                        logger.trace("old>>>" + lastModified + " ;new>>>" + tmpLastModified);
                        if (lastModified == tmpLastModified) {
                            logger.trace("   xxxxxxxxx continue   ");
                            continue;
                        }
                        lastModified = tmpLastModified;
                        //关闭锁文件，使用shell写入即可.程序检测到的话，只用调用关闭业务
//                        String content = FileUtil.getFileContent(lockFile);
                        String content = null;
                        logger.debug("content>>>>>" + content);
                        logger.debug("length>>>" + content.length());
                        if (null != content && !"".endsWith(content) && content.startsWith("STOPED")) {
                            logger.info(">>>> lockFile 文件内容修改关闭服务应用开始");
                            //退出所有容器
                            closeApp(context);
                            System.exit(0);
                            break;
                        }
                    } catch (Exception e) {
                        e.printStackTrace(System.err);
                        logger.error("error >> 服务异常", e);
                        //如果锁文件损坏，那么程序失控
                        break;
                    }
                }
            }
        }.start();
    }

    /**
     * 关闭整个资源
     * 1. 关不dobbox
     * 2. 关闭mq的消费者
     * 3. 关闭spring容器
     * 4. 关闭线程池
     *
     * @param context
     */
    private static void closeApp(ConfigurableApplicationContext context) {
        int wait_stop_app_time = 60 * 1000;

        /**
         * 所有的资源都应该绑定在spring 容器上
         */
        logger.info("xxxxxxxxxxx >> 关闭dubbo服务开始");
//        ProtocolConfig.destroyAll();//退出dubbo 不在接受新的消费

        //由于没有注册别的依赖服务，不用ProtocolConfig.destroyAll
        AbstractRegistryFactory.destroyAll(); //关闭dubbox的注册，不在接受新的消费请求，老的请求不受影响
        logger.info("xxxxxxxxxxx >> 关闭dubbo服务完成");
        //关不mq消费者，不在接受新的消费请求
        try {
            Class clazz = Class.forName("com.ndp.fb.mq.consumer.AllConsumerHolder");
            Method destroyAll = clazz.getMethod("destroyAll", null);
            destroyAll.invoke(null, null);
            logger.error("xxxxxxxxxxx尝试关闭mq消费者完成");
        } catch (ClassNotFoundException e) {

        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            logger.error("xxxxxxxxxxx尝试关闭mq消费者异常", e);
        }

        try {
            logger.info("等待" + wait_stop_app_time + "秒钟，关闭spring");
            TimeUnit.SECONDS.sleep(wait_stop_app_time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        logger.info("xxxxxxxxxxx >> 关闭Spring服务开始");
        context.close(); //退出spring容器，释放资源
        logger.info("xxxxxxxxxxx >> 关闭Spring服务完成");
        logger.info("xxxxxxxxxxx >> 关闭线程池服务开始");
        try {
            ThreadPool.shutdown();
            for (int j = 0; j < 2; j++) {
                boolean flag = ThreadPool.awaitTermination(wait_stop_app_time, TimeUnit.SECONDS);
                logger.info("xxxxxxxxxxx尝试关闭ThreadPool j>> " + j + " ,flag >>>" + flag);
                if (flag) {
                    break;
                }
            }
        } catch (Exception e) {
            logger.error("关闭线程池异常>>>", e);
        }
        logger.info("xxxxxxxxxxx >> 关闭线程池服务完成");
        //如果还有没有使用的资源，请+在这里释放掉
    }
}
